# 通用视图
import json
import os
import random
import time
from threading import Thread
from urllib import request

from django.middleware.csrf import get_token
from django.views.generic import View
from django.shortcuts import render, reverse, redirect
from django.http import HttpResponse

# 用户和权限
from django.contrib.auth.models import User, Permission, Group
from django.contrib.auth import login, logout, authenticate

# 查找权限
from django.db.models import Q


# 登陆
class Login(View):
    def get(self, request):

        return render(request, 'login.html')

    def post(self, request):

        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        is_api = request.POST.get('is_api', '0')
        print(is_api)
        print(type(is_api))
        # 判断是否注册
        exists = User.objects.filter(username=username).exists()
        if not exists:
            return HttpResponse('<script>history.back();</script>')

        # 判断密码是否正确
        user = authenticate(username=username, password=password)
        if is_api == "1":
            if user:
                login(request, user)
                res = {'status': 'success'}
            else:
                res = {'status': 'error'}
            return HttpResponse(json.dumps(res), content_type="application/json")
        else:
            if user:
                login(request, user)
                return redirect(reverse('index'))
            else:
                return HttpResponse('<script>history.back();</script>')


# 网站首页
class Index(View):
    def get(self, request):
        if not request.user.is_authenticated:
            return redirect(reverse('login'))
        return render(request, 'index.html')


class GetCsrfToken(View):
    def get(self, request):
        csrf_token = get_token(request)
        res = {'status': 'success', 'data': {'csrf_token': csrf_token}}
        return HttpResponse(json.dumps(res), content_type="application/json")


# shell执行
# post提交执行命令提供shell和token执行,返回id值
# get请求给与id值获取执行结果
class Shell(View):

    @staticmethod
    def get_random(length=16):
        """
        生成一个指定长度的随机字符串
        """
        digits = '01234567'
        ascii_letters = "abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        str_list = [random.choice(digits + ascii_letters) for i in range(length)]
        random_str = ''.join(str_list)
        return random_str

    # 根据id获取获取文件。
    # 如果id.lock 不存在则返回结果并删除id.log和id.sh
    def get(self, request):
        id = request.GET.get('id', default='0')
        tmp_dir = "temp"
        this_paths = f'{tmp_dir}/{id}'
        if not request.user.is_authenticated:
            return redirect(reverse('login'))

        with open(f'{this_paths}.log', 'r') as file:
            file_data = file.read()
            status = "loading"
            if not os.path.isfile(f'{this_paths}.lock'):
                status = 'success'
                os.remove(f'{this_paths}.sh')
                os.remove(f'{this_paths}.log')
            res = {'status': status, 'data': {'msg': f'{file_data}'}}
            return HttpResponse(json.dumps(res), content_type="application/json")

    def threadFun(self, shell, back_key):
        shell = f"{shell}"
        tmp_dir = "temp"
        this_paths = f'{tmp_dir}/{back_key}'
        os.system(f"unbuffer bash {this_paths}.sh > {this_paths}.log")
        os.remove(f"{this_paths}.lock")

    # 生成临时id 将shell命令保存到文件 id.sh 中，
    # unbuffer bash id.sh > id.log
    # 以子线程的方式执行此命令,执行开始创建 id.lock 锁，结束删除id.lock锁
    def post(self, request):
        if not request.user.is_authenticated:
            return redirect(reverse('login'))
        shell = request.POST.get('shell_input', '')
        print(shell)
        back_key = time.strftime("%Y_%m_%d-%H_%M_%S-", time.localtime()) + self.get_random(5)
        res = {'status': 'success', 'data': {'key': back_key}}

        shell = f"{shell}"
        tmp_dir = "temp"
        this_paths = f'{tmp_dir}/{back_key}'
        if not os.path.exists(tmp_dir):
            os.makedirs(tmp_dir)
        this_paths = f'{tmp_dir}/{back_key}'
        with open(f'{this_paths}.sh', 'w') as file:
            file.write(shell)
        with open(f'{this_paths}.lock', 'w') as file:
            file.write(shell)

        thread1 = Thread(target=self.threadFun, args=(shell, back_key))
        thread1.start()

        return HttpResponse(json.dumps(res), content_type="application/json")


# 用户注销
class LogoutUser(View):
    def get(self, request):
        logout(request)
        return redirect(reverse('login'))
